﻿using System;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraPrinting;

namespace Barkod.Utility.Grid
{
    public class GridUtility
    {

        #region Members
        private GridView gridView;
        bool showValidationException = true;

        public GridView GridView
        {
            get { return gridView; }
            set { gridView = value; }
        }

        public bool ShowValidationException
        {
            get { return showValidationException; }
            set { showValidationException = value; }
        }
        #endregion

        #region Constructors
        public GridUtility(GridView view)
        {
            this.gridView = view;
        }

        public GridUtility(GridManager gridManager)
        {
            this.gridView = gridManager.GridView;
        }

        #endregion

        private void SetFocusedGridValue(int rowHandle, GridColumn column, object val)
        {
            try
            {
                val = val.ToString().Trim();
                if (val.ToString() == string.Empty)
                {
                    GridView.SetRowCellValue(rowHandle, column, DBNull.Value);
                    return;
                }

                #region SetValueByControlType
                if (column.ColumnEdit is RepositoryItemGridLookUpEdit ||
                    column.ColumnEdit is RepositoryItemSearchLookUpEdit)
                {
                    RepositoryItemGridLookUpEditBase ri = column.ColumnEdit as RepositoryItemGridLookUpEditBase;

                    System.Data.DataView dt;
                    if (ri.DataSource.GetType() == typeof(System.Data.DataView))
                        dt = (System.Data.DataView)ri.DataSource;
                    else
                        dt = ((System.Data.DataTable)ri.DataSource).DefaultView;

                    System.Data.DataRow[] dr = dt.ToTable().Select(ri.DisplayMember + "='" + val + "'");
                    if (dr != null && dr.Length >0)
                    {
                        val = dr[0][ri.ValueMember];
                        GridView.SetRowCellValue(rowHandle, column, val);
                    }
                }
                else
                {
                    ShowValidationException = false;
                    try
                    {
                        //Yapıştırırken sorun olursa hata mesajı göstermesini sağlamak için                        
                        GridView.SetRowCellValue(rowHandle, column, val);
                    }
                    catch (Exception)
                    {
                    }
                    ShowValidationException = true;
                }
                #endregion
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Copy()
        {
            //GridView.OptionsBehavior.CopyToClipboardWithColumnHeaders
            bool val = GridView.OptionsBehavior.CopyToClipboardWithColumnHeaders;
            GridView.OptionsBehavior.CopyToClipboardWithColumnHeaders = false;
            GridView.CopyToClipboard();
            GridView.OptionsBehavior.CopyToClipboardWithColumnHeaders = val;

          
        }

        public void CopyWithHeaders()
        {
            bool val = GridView.OptionsBehavior.CopyToClipboardWithColumnHeaders;
            GridView.OptionsBehavior.CopyToClipboardWithColumnHeaders = true;
            GridView.CopyToClipboard();
            GridView.OptionsBehavior.CopyToClipboardWithColumnHeaders = val;
        }

        public void Export(string extension)
        {
            string fileName = "";
            foreach (DevExpress.XtraGrid.Columns.GridColumn col in GridView.Columns)
                col.MinWidth = GridView.CalcColumnBestWidth(col);

            switch (extension.ToLower())
            {
                case "pdf":
                    fileName =FileManager.SaveFile("PDF Document", "PDF Files|*.pdf");
                    GridView.ExportToPdf(fileName);
                    break;
                case "rtf":
                    fileName = FileManager.SaveFile("RTF Document", "RTF Documents|*.rtf");
                    GridView.ExportToRtf(fileName);
                    break;
                case "xlsx":
                    fileName = FileManager.SaveFile("Excel Document", "Excel Documents|*.xlsx");
                    XlsxExportOptions opt = new XlsxExportOptions();
                    opt.TextExportMode = TextExportMode.Text;
                    bool org = GridView.OptionsView.AllowCellMerge;
                    GridView.OptionsView.AllowCellMerge = false;
                    GridView.ExportToXlsx(fileName, opt);
                    GridView.OptionsView.AllowCellMerge = org;
                    break;
            }
            if (XtraMessageBox.Show("Would you like to open the document?", "Send...", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                FileManager.RunFile(fileName);
        }

        public void SelectAll()
        {
            GridView.SelectAll();
        }

      

        public string GetSelectionInfo()
        {
            double Sum = 0.0;
            int Count = 0;
            int NumericCount = 0;

            GridCell[] cells = GridView.GetSelectedCells();

            foreach (GridCell cell in cells)
            {
                object val = GridView.GetRowCellDisplayText(cell.RowHandle, cell.Column);

                if (val.ToString() != string.Empty)
                    Count++;

                if (GridView.GetRowCellValue(cell.RowHandle, cell.Column) != null)
                    if (GridView.GetRowCellValue(cell.RowHandle, cell.Column).GetType() != typeof(DateTime))
                    {
                        double dValue = 0;
                        if (double.TryParse(val.ToString(), out dValue))
                            NumericCount++;

                        Sum += dValue;
                    }
            }

            int RowCount = GridView.SelectedRowsCount;

            double Avarage = 0.0;
            Avarage = Sum > 0 ? Sum / NumericCount : 0;

            return "Adet:" + Count + "\t Sum:" + Sum.ToString("N") + "\t Avg:" + Avarage.ToString("N");
        }


        public void DeleteValue()
        {
            GridCell[] cells = GridView.GetSelectedCells();
            if (cells.Length > 0)
                foreach (GridCell cell in cells)
                {
                    if (!IsReadOnly(cell.Column))
                        GridView.SetRowCellValue(cell.RowHandle, cell.Column, DBNull.Value);
                }
            //GridView.SetFocusedValue(null);
        }

        public void DeleteRow()
        {
            try
            {
                if (!IsReadOnly(GridView)/* && GridView.Tag == null*/)
                {
                    if (GridView.Columns.Contains(GridView.Columns["Deleted"]))
                    {
                        foreach (int rowHandle in GridView.GetSelectedRows())
                        {
                            bool Deleted = false;
                            if (GridView.GetRowCellValue(rowHandle, "Deleted") != DBNull.Value)
                                Deleted = (bool)GridView.GetRowCellValue(rowHandle, "Deleted");
                            GridView.SetRowCellValue(rowHandle, "Deleted", !Deleted);
                        }
                    }
                    else
                    {
                        if (XtraMessageBox.Show("Are You Sure ?", "Delete Row", MessageBoxButtons.YesNo) == DialogResult.Yes)
                        {
                            if (GridView.SelectedRowsCount > 0)
                                GridView.DeleteSelectedRows();
                            else
                                GridView.DeleteRow(GridView.FocusedRowHandle);
                        }
                    }
                    GridView.UpdateCurrentRow();

                }
            }
            catch (Exception Ex)
            {
                MessageBox.Show(Ex.Message);
            }

        }


        private bool IsNewItemRowFocused
        {
            get
            {
                return GridView.IsNewItemRow(GridView.FocusedRowHandle);
            }
        }

        public bool PasteFromClipboard()
        {
            if (IsReadOnly(GridView))
                return false;

            if (GridView.IsFilterRow(GridView.FocusedRowHandle))
                return false;

            if (GridView.IsEditing)
                return false;

            IDataObject kopyalananVeri = Clipboard.GetDataObject();

            //Kopyalanan içerik text değil
            if (!kopyalananVeri.GetDataPresent(DataFormats.Text))
                return false;

            //Trim yapılmamalı, belki boş hücre kopyalanmıştır           
            string Kaynak = ((string)kopyalananVeri.GetData(DataFormats.Text)).Replace(" mt.", "").Replace("'", "’");
            if (Kaynak == String.Empty)
                return false;

            int KopyalananSatirSayisi = -1;
            int KopyalananSutunSayisi = -1;

            //RemoveEmptyEntries 'in sakıncası yok, zira boş satırlar \r olarak geliyor.
            string[] KopyalananSatirlar = Kaynak.Split(new char[] {'\n'}, StringSplitOptions.RemoveEmptyEntries);
            KopyalananSatirSayisi = KopyalananSatirlar.Length;
            KopyalananSutunSayisi = KopyalananSatirlar[0].Split('\t').Length;

            bool KaynakTekHucreMi = (KopyalananSutunSayisi == 1 && KopyalananSatirSayisi == 1);

            GridCell[] HedefHucreler = GridView.GetSelectedCells();
            //Hedefin tek hücre olması ya tek hücre seçilmiş olması ya de NewItemRow'da focused olması anlamına gelir.
            //NewItemRowFocused ise selectedCells 0 geliyor.
            bool HedefTekHucreMi = HedefHucreler.Length == 1 || IsNewItemRowFocused;


            int ilkSatir = GridView.FocusedRowHandle;
            if (IsNewItemRowFocused)
                ilkSatir = GridView.RowCount-1;

            int ilkSutun = GridView.FocusedColumn.VisibleIndex;
            
            GridColumn sonSutun = GridView.VisibleColumns[GridView.VisibleColumns.Count - 1];
            if (! (ilkSutun + KopyalananSutunSayisi > GridView.VisibleColumns.Count - 1))                
                sonSutun = GridView.VisibleColumns[ilkSutun + KopyalananSutunSayisi-1];
            
            try
            { 
                #region Tek hücre kopyalandı, bütün seçili hücrelere yapıştır
                if (KaynakTekHucreMi)
                {
                    if (IsNewItemRowFocused)
                    {
                        GridView.AddNewRow();
                        //Her eklenen kaydın geçerli olabilmesi için update edilmesi gerekiyor.
                        GridView.UpdateCurrentRow();
                        SetFocusedGridValue(ilkSatir, GridView.VisibleColumns[ilkSutun], Kaynak);
                    }
                    else
                    {
                        foreach (GridCell cell in GridView.GetSelectedCells())
                        {
                            if (!IsReadOnly(cell.Column))
                                SetFocusedGridValue(cell.RowHandle, cell.Column, Kaynak);
                        }
                    }
                }
                #endregion
                else
                {
                    #region Gerekli miktarda satır ekle
                    int AsagidaKalanSatirSayisi = 0;
                    //NewItemRow da aşağıda hiç satır yok demektir (=0). NewItemRow da odaklanılmamışsa aşağıdaki satırlar hesaplanır;
                    if (!IsNewItemRowFocused)
                        AsagidaKalanSatirSayisi = GridView.RowCount - GridView.FocusedRowHandle -
                            (GridView.OptionsView.NewItemRowPosition != NewItemRowPosition.None ? 1 : 0);   //FIX: OA

                    if (KopyalananSatirSayisi > AsagidaKalanSatirSayisi)
                    {
                        int EklenmesiGerekenSatirSayisi = KopyalananSatirSayisi - AsagidaKalanSatirSayisi;

                        GridView.CloseEditor();
                        GridView.UpdateCurrentRow();

                        for (int i = 0; i < EklenmesiGerekenSatirSayisi; i++)
                        {
                            //Focused cell değişiyor
                            GridView.AddNewRow();
                            //Her eklenen kaydın geçerli olabilmesi için update edilmesi gerekiyor.
                            GridView.UpdateCurrentRow();
                        }
                    }
                    #endregion
                   
                    for (int satirIndex = 0 ; satirIndex < KopyalananSatirSayisi;satirIndex++)
                    {
                        string satir = KopyalananSatirlar[satirIndex];
                        
                        string[] hucreler = satir.Split('\t');

                        for (int sutunIndex = 0; sutunIndex < KopyalananSutunSayisi; sutunIndex++)
                        {
                            string deger = hucreler[sutunIndex];
                            int SiradakiColumnIndex = ilkSutun + sutunIndex;
                            if (SiradakiColumnIndex > GridView.VisibleColumns.Count - 1)
                                break;

                            int SiradakiRowIndex = ilkSatir + satirIndex;

                            if (!IsReadOnly(GridView.VisibleColumns[SiradakiColumnIndex]))
                                SetFocusedGridValue(SiradakiRowIndex , GridView.VisibleColumns[SiradakiColumnIndex], deger);
                        }
                    }
                }

                //Yapıştırılan alanı seç                
                if (!KaynakTekHucreMi)
                {
                    GridView.ClearSelection();
                    GridView.SelectCells(ilkSatir, GridView.VisibleColumns[ilkSutun], ilkSatir + KopyalananSatirSayisi - 1, sonSutun);
                }                
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }



        //If the ReadOnly property is set to true, the cell values of columns cannot be modified by end-users. In this case cell editors can be invoked but end users can only select and copy an editor's content. 
        //This option is not in effect if the column's AllowEdit or the View's ColumnView.Editable option is disabled.
        //That is, if ReadOnly=False, an end-user can activate the in-place editor for copying its value to the clipboard, but cannot modify the value. If AllowEdit=False, the in-place editor cannot be open either.

        public static bool IsReadOnly(GridColumn col)
        {
            return col.View.OptionsBehavior.ReadOnly || !col.OptionsColumn.AllowEdit;
        }

        public static bool IsReadOnly(GridView GridView)
        {
            return GridView.OptionsBehavior.ReadOnly;
        }

        #region Move Functions
        public void MoveDown(bool Select)
        {
            int rowIndex = GridView.FocusedRowHandle;
            if (rowIndex == GridView.RowCount)
            {
                return;
            }

            int firstRowIndex = rowIndex;
            DevExpress.XtraGrid.Columns.GridColumn col = GridView.FocusedColumn;

            string nextValue = GridView.GetRowCellDisplayText(rowIndex + 1, col).ToString();

            if (nextValue == "")
            {
                while (nextValue == "" && rowIndex < GridView.RowCount - 1)
                {
                    rowIndex++;
                    nextValue = GridView.GetRowCellDisplayText(rowIndex, col).ToString();
                }
                rowIndex++;
            }
            else
            {
                while (nextValue != "" && rowIndex < GridView.RowCount - 1)
                {
                    rowIndex++;
                    nextValue = GridView.GetRowCellDisplayText(rowIndex, col).ToString();
                }
                if (rowIndex == GridView.RowCount - 1)
                    rowIndex++;
            }

            rowIndex--;
            GridView.FocusedRowHandle = rowIndex;

            if (Select)
            {
                //GridView.ClearSelection();                
                GridView.SelectCells(firstRowIndex, col, rowIndex, col);
            }
        }
        public void MoveUp(bool Select)
        {
            int rowIndex = GridView.FocusedRowHandle;
            if (rowIndex == 0)
            {
                return;
            }

            int firstRowIndex = rowIndex;
            DevExpress.XtraGrid.Columns.GridColumn col = GridView.FocusedColumn;

            string nextValue = GridView.GetRowCellDisplayText(rowIndex - 1, col).ToString();

            if (nextValue == "")
            {
                while (nextValue == "" && rowIndex > 0)
                {
                    rowIndex--;
                    nextValue = GridView.GetRowCellDisplayText(rowIndex, col).ToString();
                }
                rowIndex--;
            }
            else
            {
                while (nextValue != "" && rowIndex > 0)
                {
                    rowIndex--;
                    nextValue = GridView.GetRowCellDisplayText(rowIndex, col).ToString();
                }
                if (rowIndex == 0)
                    rowIndex--;
            }

            rowIndex++;
            GridView.FocusedRowHandle = rowIndex;

            if (Select)
            {
                //GridView.ClearSelection();
                GridView.SelectCells(firstRowIndex, col, rowIndex, col);
            }
        }
        public void MoveRight(bool Select)
        {
            DevExpress.XtraGrid.Columns.GridColumn col = GridView.FocusedColumn;
            int colIndex = col.ColumnHandle;
            if (colIndex == GridView.Columns.Count - 1)
            {
                return;
            }

            int rowIndex = GridView.FocusedRowHandle;
            int firstColIndex = colIndex;

            string nextValue = GridView.GetRowCellDisplayText(rowIndex, GridView.Columns[colIndex + 1]).ToString();

            if (nextValue != "")
            {
                while (nextValue != "" && colIndex < GridView.Columns.Count - 1)
                {
                    colIndex++;
                    nextValue = GridView.GetRowCellDisplayText(rowIndex, GridView.Columns[colIndex]).ToString();
                }
                colIndex--;
            }
            else
            {
                while (nextValue == "" && colIndex < GridView.Columns.Count - 1)
                {
                    colIndex++;
                    nextValue = GridView.GetRowCellDisplayText(rowIndex, GridView.Columns[colIndex]).ToString();
                }
            }

            GridView.FocusedColumn = GridView.Columns[colIndex];

            if (Select)
            {
                //GridView.ClearSelection();
                GridView.SelectCells(rowIndex, GridView.Columns[firstColIndex], rowIndex, GridView.Columns[colIndex - 1]);
            }

        }
        public void MoveLeft(bool Select)
        {
            DevExpress.XtraGrid.Columns.GridColumn col = GridView.FocusedColumn;
            int colIndex = col.ColumnHandle;
            if (colIndex == 0)
            {
                return;
            }
            int rowIndex = GridView.FocusedRowHandle;
            int firstColIndex = colIndex;

            string nextValue = GridView.GetRowCellDisplayText(rowIndex, GridView.Columns[colIndex - 1]).ToString();

            if (nextValue != "" && colIndex > 0)
            {
                while (nextValue != "" && colIndex > 0)
                {
                    colIndex--;
                    nextValue = GridView.GetRowCellDisplayText(rowIndex, GridView.Columns[colIndex]).ToString();
                }
                colIndex++;
            }
            else
            {
                while (nextValue == "" && colIndex > 0)
                {
                    colIndex--;
                    nextValue = GridView.GetRowCellDisplayText(rowIndex, GridView.Columns[colIndex]).ToString();
                }
            }

            GridView.FocusedColumn = GridView.Columns[colIndex];


            if (Select)
            {
                //GridView.ClearSelection();
                GridView.SelectCells(rowIndex, GridView.Columns[firstColIndex], rowIndex, GridView.Columns[colIndex - 1]);
            }
        }
        #endregion
    }
}